package com.bytech.admin.biz.interceptor;

import java.lang.reflect.Method;
import java.util.Arrays;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.bytech.admin.biz.annotation.CheckIdempotent;
import com.bytech.admin.biz.annotation.GrantIdempotent;
import com.bytech.admin.biz.exception.BlogAdminRuntimeException;
import com.bytech.common.utils.JedisClient;
import com.bytech.common.utils.StringUtils;

import static com.bytech.common.biz.entity.base.BlogResultStatus.*;

/**
 * @Author Zhao
 * @Create 2021/11/20 11:28
 */
@Component
public class IdempotentInterceptor implements HandlerInterceptor {

    private static final String IDEMPOTENT_COOKIE_KEY = "IDT";
    private static final String IDEMPOTENT_FOLDER = "idempotent";

    @Resource
    private JedisClient jedisClient;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        CheckIdempotent checkIdempotent = method.getAnnotation(CheckIdempotent.class);
        if (checkIdempotent == null) {
            return true;
        } else {
            String tag = checkIdempotent.tag();
            if (!StringUtils.isBlank(tag)) {
                Cookie cookie = Arrays.stream(request.getCookies())
                        .filter(e -> e.getName().equals(String.format("%s_%s", IDEMPOTENT_COOKIE_KEY, tag))).findFirst().orElse(null);
                if (cookie == null) {
                    throw new BlogAdminRuntimeException(IDEMPOTENT_NO_EXIST_ERROR);
                }
                String idempotentKey = String.format("%s:%s:%s", IDEMPOTENT_FOLDER, tag, cookie.getValue());
                if (jedisClient.go((cluster) -> cluster.del(idempotentKey)) != 1) {
                    throw new BlogAdminRuntimeException(IDEMPOTENT_ERROR);
                }
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable ModelAndView modelAndView) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        GrantIdempotent grantIdempotent = method.getAnnotation(GrantIdempotent.class);
        if (grantIdempotent != null) {
            String tag = grantIdempotent.tag();
            if (!StringUtils.isBlank(tag)) {
                String key = StringUtils.getUUID32();
                String idempotentKey = String.format("%s:%s:%s", IDEMPOTENT_FOLDER, tag, key);
                jedisClient.go((cluster) -> cluster.set(idempotentKey, ""));
                response.addCookie(new Cookie(String.format("%s_%s", IDEMPOTENT_COOKIE_KEY, tag), key));
            }
        }
    }
}
